package com.fh.service.loantaskimpl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.fh.dao.DaoSupport;
import com.fh.mapper.loan.CallLoanInfoMapper;
import com.fh.mapper.loan.SysUserMapper;
import com.fh.model.Page;
import com.fh.model.loan.CallLoanInfo;
import com.fh.model.loan.CallLoanInfoDto;
import com.fh.model.loan.SysUser;
import com.fh.model.loan.TransferHistoryInfo;
import com.fh.service.cuijimanage.CuijimanageServiceImpl;
import com.fh.util.Const;
import com.fh.util.PageData;
import com.fh.util.R;
import com.fh.util.UserUtils;

/**
 * LiGuangYi
 * 催收中service
 *
 * @author dell、
 */
@Service
public class LoanTaskUnderServiceImpl {

    private Logger logger = org.slf4j.LoggerFactory.getLogger(LoanTaskUnderServiceImpl.class);

    @Autowired
    private CallLoanInfoMapper callloaninfomapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private CuijimanageServiceImpl cuijimanageServiceImpl;

    @Autowired
    private LoanTaskOverServiceImpl loanTaskOverService;

    @Autowired
	private DaoSupport dao;
    /**
     * 催收中任务列表
     *
     * @param page
     * @return
     * @throws Exception
     */
    public List<PageData> findLoanTaskListPage(Page page) throws Exception {
        R.setPageHelper(page.getPd());
        List<PageData> taskPlistPage = callloaninfomapper.findTaskPListPage(page);
        R.setPage(page,taskPlistPage);
        return taskPlistPage;
    }

    /**
     * 用户列表
     *
     * @param page
     * @return
     * @throws Exception
     */
    public List<PageData> findUserListPage(Page page) throws Exception {
        return sysUserMapper.findUserlistPage(page);
    }

    /**
     * 案件分派
     *
     * @param para
     * @return
     */
    @Transactional
    public int updateLoanByUserIds(Map<String, Object> para) {
        return callloaninfomapper.updateUserIds(para);
    }

    /**
     * 催收中分派
     *
     * @param para
     * @return
     */
    @Transactional
    public int updateUserIdsByToBe(Map<String, Object> para) {
        return callloaninfomapper.updateUserIdsByToBe(para);
    }

    /**
     * 案件标记
     *
     * @param request
     * @param ids
     * @param ids1
     * @return
     */
    public Map<String, Object> getLabel(HttpServletRequest request, String[] ids, String[] ids1) {
        int a = 0;
        request.getAttribute("ids");
        if (Const.SING_STATUS_ZERO != ids.length) {
            Map<String, Object> para = new HashMap<>();
            para.put("ids", ids);
            para.put("status", Const.SIGN_STATUS_ONE);
            para.put("updateTime", new Date());
            a = cuijimanageServiceImpl.updateCallRemarkStatus(para);
        }
        int a1 = 0;
        if (Const.SING_STATUS_ZERO != ids1.length) {
            Map<String, Object> para1 = new HashMap<>();
            para1.put("ids", ids1);
            para1.put("status", Const.SING_STATUS_ZERO);
            para1.put("updateTime", new Date());
            a1 = cuijimanageServiceImpl.updateCallRemarkStatus(para1);
        }
        Map<String, Object> resp = new HashMap<>();
        resp.put("num", a + a1);
        return resp;
    }


    /**
     * 批量分派
     *
     * @param userId  用户ID
     * @param request
     * @param flag
     * @return
     */
    public Map<String, Object> getUserIdsByAssign(String userId, HttpServletRequest request, String flag) {
        Map<String, Object> map = new HashMap<>();
        String[] ids = (String[]) request.getSession().getAttribute("fpId");
        String currentUserId = request.getParameter("currentUserId");
        if (Const.SING_STATUS_ZERO != ids.length) {
            map.put("usid", userId);
            map.put("ids", ids);
            map.put("call_time", new Date());
            if (Const.SIGN_STATUS_STRING_ONE.equals(flag)) {
            	insertTransHis(ids, userId, currentUserId,0);
                this.updateUserIdsByToBe(map);
            } else {
            	insertTransHis(ids, userId, currentUserId,0);
                this.updateLoanByUserIds(map);
            }
        }
        request.getSession().removeAttribute("fpId");
        return map;
    }

    /**
     * 根据page查询分派所需要的Nid
     *
     * @return
     */
    public List<CallLoanInfoDto> selectCallLoanNidByPageDate(Page page, Integer num) {
        PageData pd = page.getPd();
        pd.put("num", num);
        return callloaninfomapper.selectCallLoanNidByPageDate(page);
    }

    /**
     * 新批量
     *
     * @param page    需要的筛选条件
     * @param userIds 被选中将要分配案件的用户id
     * @param num     需要分配的案件总数
     * @throws Exception
     */
    @Deprecated
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void updataCallLoanInfoUserIdss(Page page, Integer[] userIds, Integer num, HttpServletRequest request) throws Exception {
        if (num != 0 && !Objects.equals("", num)) {
            Map<String, Object> map = new HashMap<>();
            //人员数量
            int length = userIds.length;
            //对人员及需要分配的案件总数进行取于所得若为0则可被整除,并平均分配,若为0则更换规则
            int quyu = num % length;
            //将要循环的次数
            int xunHuanNum = num / length;
            //取出将要进行操作的数据 总任务
            if (Objects.nonNull(page)) {
                PageData pd = page.getPd();
                Integer status = (Integer) pd.get("status");
                List<CallLoanInfoDto> totalTask = this.selectCallLoanNidByPageDate(page, num);
               // String currentUserId = request.getParameter("currentUserId");
                String currentUserId = (Integer)pd.get("currentUserId")+"" ;
                for (int h = 0; h < length; h++) {
                    System.out.println("人员:" + h);
                    Integer userId = userIds[h];
                    int start = h * xunHuanNum;
                    int end = (h + 1) * xunHuanNum;
                    List userList = totalTask.subList(start, end);
                    map.put("usid", userId);
                    map.put("ids", userList);
                    map.put("status",status);
                    map.put("call_time", new Date());
                    if (!Objects.equals(userList, null) && userList.size() > 0) {
                        callloaninfomapper.updateUserIdsByToBe2(map);
                        insertTransHis((String[]) userList.toArray(new String[userList.size()]), String.valueOf(userId), currentUserId,status);
                    }
                }
            }
        }
    }
    public static void main(String[] args) {
        getAvgList(10,5,12,25,30);
        getAvgList(1000,2000,500,300,1500,600,700,1100);
    }
    public void rankMap( List<PageData> totalTask){
        Map<String , String> map = new Hashtable<>();
        for (PageData pageData : totalTask) {

        }
    }

    /**
     * 平均分派
     * 委外催收中+委内待催收
     * @param page    需要的筛选条件
     * @param userIds 被选中将要分配案件的用户id
     * @param num     需要分配的案件总数
     * @throws Exception
     */
    @Transactional(readOnly=false,propagation= Propagation.REQUIRED)
    public void updataCallLoanInfoUserIds(Page page, Integer[] userIds, Integer num, HttpServletRequest request) throws Exception {
        if (num != 0 && !Objects.equals("", num)) {
            //人员数量
            int length = userIds.length;
            //对人员及需要分配的案件总数进行取于所得若为0则可被整除,并平均分配,若为0则更换规则
            int quyu = num % length;
            //将要循环的次数
            int xunHuanNum = num / length;
            //取出将要进行操作的数据 总任务
            if (Objects.nonNull(page)) {
                PageData pd = page.getPd();
                Integer status = (Integer) pd.get("status");
                List<CallLoanInfoDto> totalTask = this.selectCallLoanNidByPageDate(page, num);
                int size = totalTask.size();
                totalTask.removeAll(totalTask.subList(size - quyu, size));
                //遍历金额后拿到催收编号
                List<String> dList=new ArrayList<String>();
                for(int j=0;j<totalTask.size();j++){
                    dList.add(totalTask.get(j).getCallLoanNid());
                }
                Map<Integer, List<String>> map = new HashMap<Integer, List<String>>();
                //初始化map
                List<String> list = null;
                int k = userIds.length - 1;//催收员数量
                for (; k >= 0; k--) {
                    list = new ArrayList<String>();
                    int sum = userIds[k];
                    map.put(sum, list);
                }
                //分配催缴单
                divideDebit(dList,userIds.length,true,map,userIds);
                //打印分配结果
                for(Integer key:map.keySet()){//USER_ID
                    List<String> userList = new ArrayList<>();
                    for(String i:map.get(key)){
                        userList.add(i);//call_loan_nid
                    }
                    Map<String, Object> hashMap = new HashMap<>();
                    hashMap.put("usid", key);
                    hashMap.put("ids", userList);
                    hashMap.put("status", status);
                    try {
                        if (0 == status) {
                            logger.info("内催批量分派案件执行---------------------------->>"+hashMap.toString());
                            callloaninfomapper.updateUserIdsByToBe2(hashMap);
                        } else if (3 == status) {
                            logger.info("委外批量分案件派执行---------------------------->>"+hashMap.toString());
                            callloaninfomapper.updateUserIdsByToBeWieWai(hashMap);
                        }
                    } catch (Exception e){
                        logger.error("批量分派异常*******************************************************************************************"+e.getMessage());
                    }
                    //新增流转记录
                    List<TransferHistoryInfo> transferHistoryInfolist = getTransferHistoryInfolist(userList, status,key);//当前催收员所用分配的案件
                    dao.batchSave2("com.fh.mapper.loan.TransferHistoryInfoMapper.insert", transferHistoryInfolist);
                    callloaninfomapper.updateUserIdsByToBe2(hashMap);
                }

            }
        }
    }
    /**
     * 平均分派的流转记录
     * 
     */
    public List<TransferHistoryInfo>  getTransferHistoryInfolist(List<String> list,Integer status,Integer USER_ID){
    	List<TransferHistoryInfo> transferHistoryInfolist = new ArrayList<>();
    	Map<String, Object> userMap = cuijimanageServiceImpl.findUserByUserId(String.valueOf(USER_ID));
    	String userName = (String) userMap.get("name");
    	
		for (String callLoanNid : list) {
			 TransferHistoryInfo transferHistoryInfo = new TransferHistoryInfo();
			 Map<String,Object> parm = new HashMap<>();
			 //案件编号
			 parm.put("callLoanNid",callLoanNid);
			 CallLoanInfo callLoanInfo = callloaninfomapper.findCallLoanInfoSingle(parm);
			 transferHistoryInfo.setCallLoanNid(callLoanNid);
			 transferHistoryInfo.setOverdueStage(callLoanInfo.getOverdueStage());
			 transferHistoryInfo.setStartTime(new Date());
			 //当前状态(委外催收中或者委内催收中)
			 transferHistoryInfo.setCurrentStatus(status == 0 ? 1 : 3);
			 transferHistoryInfo.setOperator(UserUtils.getUser().getUSER_ID());
			 transferHistoryInfo.setTransferDesc(status == 0 ? "平均分派:转入"+ userName+ "(ID:"+ USER_ID +")" : "委外平均分派:转入"+ userName+ "(ID:"+ USER_ID +")");
			 transferHistoryInfo.setUpdateTime(new Date());
			 transferHistoryInfo.setCreateTime(new Date());
			 transferHistoryInfo.setToCallUid(USER_ID);//当前催收员
			 transferHistoryInfo.setFromCallUid(callLoanInfo.getCallUser()==null ? -1 : callLoanInfo.getCallUser());//之前催收员
			 transferHistoryInfo.setOverdueCaptial(callLoanInfo.getOverdueCaptial());//流转当期逾期本金
			 transferHistoryInfo.setOverdueInterest(callLoanInfo.getOverdueInterest());//流转当期逾期利息
			 transferHistoryInfo.setOverdueManFee(callLoanInfo.getOverdueManFee());//流转当期逾期管理费
			 transferHistoryInfo.setOverdueSerFee(callLoanInfo.getOverdueSerFee());//流转当期逾期服务费
			 transferHistoryInfo.setInOverdueFee(callLoanInfo.getOverdueFee());//流转当期逾期罚息
			 transferHistoryInfolist.add(transferHistoryInfo);
		 }
		 return transferHistoryInfolist;
	 }
    
    public void divideDebit(List<String> dList,Integer num,boolean direction,Map<Integer,List<String>> map,Integer[] userIds){
        if(dList.size()>=num){//账单大于人数
            for(int i=0;i<num;i++){
                Integer user;
                if(direction){
                    user=userIds[i];
                }else{
                    user=userIds[num-i-1];
                }
                List<String> list=map.get(user);
                if(!"".equals(dList.get(i))){
                    list.add(dList.get(i));
                    map.put(user, list);
                }
            }
            //去除已经分配的账单
            List<String> newDebitList=new ArrayList<String>();
            for(int i=0;i<dList.size();i++){
                if(i>num-1){
                    newDebitList.add(dList.get(i));
                }
            }
            if(newDebitList.size()>0){
                //下次分配账单，按反方向分配
                divideDebit(newDebitList,num,!direction, map,userIds);
            }
        }
    }

    private static void getAvgList(Integer...t){
        List<Integer> a = Arrays.asList(t);
        a = a.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        System.out.println("old ==>" + a);
        Double val = a.stream().mapToInt(x -> x).average().getAsDouble();
        System.out.println("平均值 ==》" + val);
        List<Integer> maxList = new ArrayList<>();
        List<Integer> minList = new ArrayList<>();
        maxList.addAll(a.stream().filter(x-> x> val).collect(Collectors.toList()));
        minList.addAll(a.stream().filter(x-> x<= val).collect(Collectors.toList()));
        System.out.println("最大值集合 ==》" + maxList);
        System.out.println("最小值集合 ==》" + minList);
        List<Integer> newList = new LinkedList<>();
        int len = a.size();
        for(int i = 0; i < len;i++){
            if(i < maxList.size()) {
                newList.add(maxList.get(i));
            }
            if(i < minList.size()) {
                newList.add(minList.get(i));
            }
        }
        System.out.println("new ==> " + newList);
        System.out.println("************** ");
    }
    /**
     * 批量分派流转记录
     *
     * 批量插入流转记录
     * @param ids
     * @param userId
     * @param currentUserId
     */
    public void insertTransHis(String[] ids, String userId, String currentUserId,int status) {
        Map<String, Object> map = new HashMap<String, Object>();
        Map<String, Object> userMap = cuijimanageServiceImpl.findUserByUserId(userId);
        List<TransferHistoryInfo> transferHistoryInfoList = new ArrayList<>();
        try {
            String userName = (String) userMap.get("name");
            for (int i = 0; i < ids.length; i++) {
            	TransferHistoryInfo transferHistoryInfo = new TransferHistoryInfo();
                map.put("ids", ids[i]);
                CallLoanInfo callLoanInfo = cuijimanageServiceImpl.faxijianmianApplyById(ids[i]);
                transferHistoryInfo.setCallLoanNid(ids[i]);
                if(org.apache.commons.lang.StringUtils.isNotBlank(callLoanInfo.getOverdueStage())){
                	transferHistoryInfo.setOverdueStage(callLoanInfo.getOverdueStage());
                }else{
                	transferHistoryInfo.setOverdueStage("无");//如果逾期阶段为空默认设为无
                }
                transferHistoryInfo.setCurrentStatus(Const.CONSTANT_STRUTS1);//当前状态为催收中
                if(status==3){
                	transferHistoryInfo.setCurrentStatus(3);//当前状态为委外催收中
                }
                transferHistoryInfo.setTransferDesc("批量分派：转入" + userName + "(ID:"+ userId +")");
                transferHistoryInfo.setStartTime(new Date());
                transferHistoryInfo.setOperator(Integer.valueOf(currentUserId));
                transferHistoryInfo.setCreateTime(new Date());
                transferHistoryInfo.setUpdateTime(new Date());
                transferHistoryInfo.setToCallUid(Integer.parseInt(userId));//当前催收员
	            transferHistoryInfo.setFromCallUid(callLoanInfo.getCallUser()==null ? -1 : callLoanInfo.getCallUser());//之前催收员
                transferHistoryInfo.setOverdueCaptial(callLoanInfo.getOverdueCaptial());//流转当期逾期本金
	            transferHistoryInfo.setOverdueInterest(callLoanInfo.getOverdueInterest());//流转当期逾期利息
	            transferHistoryInfo.setOverdueManFee(callLoanInfo.getOverdueManFee());//流转当期逾期管理费
	            transferHistoryInfo.setOverdueSerFee(callLoanInfo.getOverdueSerFee());//流转当期逾期服务费
	            transferHistoryInfo.setInOverdueFee(callLoanInfo.getOverdueFee());//流转当期逾期罚息
	            transferHistoryInfoList.add(transferHistoryInfo);
            }
            dao.batchSave2("com.fh.mapper.loan.TransferHistoryInfoMapper.insert", transferHistoryInfoList);
        } catch (Exception e) {
            logger.error("批量分派流转记录------------------->>", e);
        }
    }

    /**
     * 查询所有用户
     *
     * @return
     */
    public List<SysUser> userlist() {
        return sysUserMapper.findUser();
    }

    /**
     * 根据当前用户获取所有下级催收员员工
     *
     * @param userId
     * @return
     * @throws Exception
     */
    public List<SysUser> sysUsers(Integer userId, String s) throws Exception {
        String currentUserId = String.valueOf(userId);
        Map<String, Object> map = new HashMap<>();
        String[] arraysUser = null;
        List<SysUser> userByIds = null;
        List<SysUser> userByIdsAll = null;
        if (null != currentUserId && !"".equals(currentUserId)) {
            // 查出所有的子类id
            userByIds = sysUserMapper.findUserByIdsTo(currentUserId, s);
            if (null != userByIds && userByIds.size() > Const.SING_STATUS_ZERO) {
                arraysUser = new String[userByIds.size()];
                for (int i = 0; i < userByIds.size(); i++) {
                    arraysUser[i] = userByIds.get(i).getUserid();
                }
                map.put("arraysUserIds", arraysUser);
                map.put("userid", userId);
                // 查出所有的子类的子类id
                userByIdsAll = sysUserMapper.findUserByIdsAll(map, s);
                String role_ID = UserUtils.getUser().getROLE_ID();
                if (null != userByIdsAll || userByIdsAll.size() > Const.SING_STATUS_ZERO || role_ID.equals(Const.ROLE_CSJL)) {
                    // 登录为催收经理(清空催收组长的数据)
                    userByIds = new ArrayList<SysUser>();
                    userByIds.addAll(userByIdsAll);
                }
            }
            return userByIds;
        }
        return null;
    }
    
    public SysUser findObjByUserId(String userId){
        return sysUserMapper.findObjByUserId(userId);
    }

    /**
     * 根据催收员姓名查找催收员ID
     *
     * @param callUserName
     * @return
     */
    public SysUser getcallUserName(String callUserName) {
        Map<String, Object> map = new HashMap<>();
        SysUser sysUser = null;
        if (!"".equals(callUserName) && callUserName != null) {
            map.put("callUserName", callUserName);
            sysUser = loanTaskOverService.findUserByUserName(map);
        }
        return sysUser;
    }

    /**
     * 根据催收员ID进行判断填充pd
     *
     * @param sysUser
     * @return
     */
    public PageData getUserId(PageData pageData, SysUser sysUser) {
        if (sysUser != null) {
            pageData.put("callUserId", sysUser.getUserid());
        } else {
            pageData.put("callUserId", " ");
        }
        return pageData;
    }


    /**
     * 导出
     *
     * @return
     */
    @Transactional
    public List<PageData> infolist(Page page) {
        return callloaninfomapper.findListInfo(page);
    }
}
